package team.bailan.common.server;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import team.bailan.common.process.ingame.InGame;
import team.bailan.common.process.ingame.InGameMap;
import team.bailan.common.process.ingame.RoomInfMap;
import team.bailan.common.process.roblord.RobLordMap;
import team.bailan.entity.domain.RoomInf;
import team.bailan.entity.vo.LeaveInfVO;
import team.bailan.entity.vo.PrepareInfVO;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint("/websocket/{roomId}/{playerPosition}")
@Component
public class WebSocketServer {
    public static WebSocketServer webSocketServer = new WebSocketServer();

    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);

    /**
     * 当前在线连接数
     */
    private static AtomicInteger onlineCount = new AtomicInteger(0);

    /**
     * 用来存放每个客户端对应的 WebSocketServer 对象
     */
    public static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;

    /**
     * 接收 roomId
     */
    private String roomId = "";

    /**
     * 接收 playerPosition
     */
    private String playerPosition = "";

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("roomId") String roomId, @PathParam("playerPosition") String playerPosition) throws IOException {
        this.session = session;
        this.roomId = roomId;
        this.playerPosition = playerPosition;
        if (webSocketMap.containsKey(roomId + "_" + playerPosition)) {
            webSocketMap.remove(roomId + "_" + playerPosition);
            webSocketMap.put(roomId + "_" + playerPosition, this);
        } else {
            webSocketMap.put(roomId + "_" + playerPosition, this);
            addOnlineCount();
        }
        log.info("房间号:" + roomId + " " + playerPosition + "号玩家连接" + ",当前在线人数为:" + getOnlineCount());
        try {
            RoomInf roomInf;
            if (RoomInfMap.roomInfMap.containsKey("room_" + roomId)) {
                roomInf = RoomInfMap.roomInfMap.get("room_" + roomId);
            } else {
                throw new Exception();
            }
            PrepareInfVO prepareInfVO = new PrepareInfVO();
            prepareInfVO.setMsgType("EnterRoomInf");
            prepareInfVO.setData(roomInf);
            prepareInfVO.setStartFlag(false);
            prepareInfVO.setPlayerPosition(Integer.parseInt(playerPosition));
            WebSocketServer.webSocketServer.sendToRoom(JSON.toJSONString(prepareInfVO), roomId + "");
        } catch (Exception e) {
            log.error("房间号:" + roomId + " " + playerPosition + "号玩家网络异常!!!!!!");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() throws Exception {
        if (webSocketMap.containsKey(roomId + "_" + playerPosition)) {
            webSocketMap.remove(roomId + "_" + playerPosition);
            if (RoomInfMap.roomInfMap.containsKey("room_" + roomId)) {
                RoomInfMap.roomInfMap.get("room_" + roomId).leaveTheRoom(Integer.parseInt(playerPosition));
            }
            RoomInf roomInf;
            if (RoomInfMap.roomInfMap.containsKey("room_" + roomId)) {
                roomInf = RoomInfMap.roomInfMap.get("room_" + roomId);
            } else {
                throw new Exception();
            }
            if (InGameMap.inGameMap.containsKey("room_" + Integer.parseInt(roomId))) {
                if (InGameMap.inGameMap.get("room_" + Integer.parseInt(roomId)).isStart()) {
                    InGame.init(Integer.parseInt(roomId));
                }
            }
            roomInf.getPrepareFlag()[Integer.parseInt(playerPosition)] = false;
            PrepareInfVO prepareInfVO = new PrepareInfVO();
            prepareInfVO.setMsgType("LeaveRoomInf");
            prepareInfVO.setData(roomInf);
            prepareInfVO.setStartFlag(false);
            prepareInfVO.setPlayerPosition(Integer.parseInt(playerPosition));
            WebSocketServer.webSocketServer.sendToRoom(JSON.toJSONString(prepareInfVO), roomId + "");
            subOnlineCount();
        }
        log.info("房间号:" + roomId + " " + playerPosition + "号玩家退出" + ",当前在线人数为:" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info(roomId + "号房间" + playerPosition + "号用户发来消息" + ",报文:" + message);
        if (!StringUtils.isEmpty(message)) {
            try {
                /*JSONObject jsonObject = JSON.parseObject(message);
                jsonObject.put("fromUserId", this.userId);
                String toUserId = jsonObject.getString("toUserId");
                if (!StringUtils.isEmpty(toUserId) && webSocketMap.containsKey(toUserId)) {
                    webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
                } else {
                    log.error("请求的 userId:" + toUserId + "不在该服务器上");
                }*/
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发生错误时调用
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error(roomId + "号房间" + playerPosition + "号玩家错误:" + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 发给某个房间的某个玩家
     */
    public void sendToUser(String message, String roomId, String playerPosition) throws IOException {
        if (webSocketMap.get(roomId + "_" + playerPosition) != null) {
            webSocketMap.get(roomId + "_" + playerPosition).sendMessage(message);
        } else {
            //如果用户不在线则返回不在线信息给自己
            // do nothing
        }
    }

    /**
     * 发给某个房间的所有玩家
     */
    public void sendToRoom(String message, String roomId) throws IOException {
        sendToUser(message, roomId, 1 + "");
        sendToUser(message, roomId, 2 + "");
        sendToUser(message, roomId, 3 + "");
    }

    public static synchronized AtomicInteger getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount.getAndIncrement();
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount.getAndDecrement();
    }
}
